package com.iflytek.jzcpx.procuracy.cont.common.util;

import java.io.ByteArrayInputStream;
import java.util.concurrent.TimeUnit;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

/**
 * 图像识别工具类
 * 
 * @author lli
 *
 * @version 1.0
 *
 */
public final class OcrUtilNew {

	private static final Logger logger = LoggerFactory.getLogger(OcrUtilNew.class);

	private static int num = 0;

	/** ocrServer websocke连接地址 **/
	// private static String url = "ws://10.1.135.35:8081/tuling/ocr/v1/do";
	private static String url = null;

	private static int timeout = 0;

	/**
	 * （传统方式）
	 * 
	 * @description 图像识别转换为文字
	 * @author lli
	 * @create 2017年8月8日上午11:19:59
	 * @version 1.0
	 * @param data
	 *            图片的字节数组
	 * @return ocr返回结果
	 * @throws Exception
	 */
	public static String queryOcr(final byte[] data) {

		String result = "";
		ocr ocr = new ocr();
		String sessionId = null;
		try {
			/** 检查图片字节流是否符合识别条件 **/
			if (!checkImageBytes(data)) {
				return result;
			}

			/** 判断是否已调用OCRSessionEnd **/
			boolean isSse = false;

			int[] errorCode = new int[1];
			String param = "svc=ocr,caseno=12,image_params=level=3;textline=-1";
			/** 获取获取本次识别的sessionId */
			sessionId = ocr.OCRSessionBegin(param, errorCode);

			if (errorCode[0] != 0) {
				logger.error("ocr连接调用失败" + errorCode[0]);
				ocr.OCRSessionEnd(sessionId);
				isSse = true;
				return "";
			}
			/** 文件长度 */
			int length = data.length;

			/** 往引擎发送文本数据 */
			int ret = ocr.OCRImageWrite(sessionId, "test.jpg", 0, data, length, 4);
			if (ret == 0) {
				logger.info("ocrImageWrite completed");
			} else {
				logger.info("OCRImageWrite 失败！错误码：{}", ret);
				ocr.OCRSessionEnd(sessionId);
				isSse = true;
				return "";
			}

			int[] result_status = new int[1];
			result_status[0] = 0;
			int[] resultStatus = new int[1];
			resultStatus[0] = 0;
			int[] globalStat = new int[1];
			globalStat[0] = 0;
			/** 获取解析的数据 */

			long start = System.currentTimeMillis();
			while (globalStat[0] != 3 && errorCode[0] == 0 && globalStat[0] != 1) {
				long time = System.currentTimeMillis() - start;
				if (time > timeout * 1000) {
					logger.info("ocr 识别超时！,超时{}ms,错误码：{}", timeout, resultStatus);
					ocr.OCRSessionEnd(sessionId);
					isSse = true;
					return "";
				}

				if (isSse) {
					logger.info(
							"session=" + sessionId + " errorCode:" + errorCode[0] + " OCRSessionEnd之后仍在OCRGetResult");
				}

				result = ocr.OCRGetResult(sessionId, globalStat, resultStatus, errorCode);

				if (resultStatus[0] == 3) {
					break;
				} else if (resultStatus[0] == 1) {
					logger.error("获取ocr出错");
					ocr.OCRSessionEnd(sessionId);
					isSse = true;
					return "";
				}
				// 延时调用 100ms
				try {
					TimeUnit.MILLISECONDS.sleep(100);
				} catch (InterruptedException e) {
				}
			}
			ocr.OCRSessionEnd(sessionId);
			isSse = true;

			/** 从解析结果中获取base64数据 */
			String ocr_json = "";
			String embdedResult = "";

			if (!StringUtils.isEmpty(result)) {
				embdedResult = JSONObject.parseObject(result).getJSONObject("result").getString("result");
				ocr_json = Base64.decodeStr(embdedResult);
				result = ocr_json;
				logger.info("解析ocr数据成功");
			}

			logger.info("获取ocr结束");
		} catch (Exception e) {
			logger.error("ocr识别出现未知异常如下：");
			logger.error(e.getMessage());
			if (!StringUtils.isEmpty(sessionId)) {
				ocr.OCRSessionEnd(sessionId);
				logger.error("ocr识别异常情况下session已释放");
			}
		}

		return result;
	}

	public static void setUrl(String newUrl) {
		url = newUrl;
	}

	/***
	 * 检查图片字节流数据是否符合条件
	 * 
	 * @return
	 */
	private static boolean checkImageBytes(byte[] data) {
		/** 文件数据校验 **/
		String fileType = "";
		if (data == null || data.length == 0) {
			logger.info("文件字节流为空");
			return false;
		}
		try {
			fileType = FileTypeUtil.getType(new ByteArrayInputStream(data));
		} catch (Exception e) {
			logger.info("获取文件类型失败");
			return false;
		}
		if (StrUtil.isBlank(fileType) || !StrUtil.containsIgnoreCase("jpg,bmp,png", fileType)) {
			logger.info("文件类型不匹配，传入的类型为：{}", fileType);
			return false;
		}

		return true;
	}

	public synchronized static int getNum() {
		return num;
	}

	public synchronized static void addNum() {
		num++;
	}

	public synchronized static void reduceNum() {
		num--;
	}

	public static void setTimeout(int timeout) {
		OcrUtilNew.timeout = timeout;
	}
}
